/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.edu.cs576.HyperLinkVideo.authoringtool;

import java.awt.image.BufferedImage;

/**
 *
 * @author Ludo
 */
public class MotionCompensation {
    private TrackingArea currentTrackingArea;
    private BufferedImage referenceFrame;
    private BufferedImage targetFrame;
    
    private int macroBlockWidth;
    private int macroBlockHeight;
    private int range;
    
    public static final double ERROR_THRESHOLD =  150000;
    
    public MotionCompensation(int k){
        range = k;
    }
    
    public void setReference(BufferedImage referenceFrame, TrackingArea area){
        this.referenceFrame = referenceFrame;
        currentTrackingArea = area;
        
        int[] topLeft = area.getTopLeft();
        int[] bottomRight = area.getBottomRight();
        macroBlockWidth = bottomRight[0] - topLeft[0];
        macroBlockHeight = bottomRight[1] - topLeft[1];
    }
    
    public void setTarget(BufferedImage target){
        targetFrame = target;
    }
    
    public TrackingArea getBestMatchingArea(){
        int width = targetFrame.getWidth();
        int height = targetFrame.getHeight();
        int[] topLeft = currentTrackingArea.getTopLeft();
        
        double mad = ERROR_THRESHOLD;
        int[] bestMatchCoord= {0,0};
        for(int j = topLeft[1]-range ; j < topLeft[1]+range; j++){
            for(int i = topLeft[0]-range ; i < topLeft[0]+range; i++){
                if(i+macroBlockWidth < width && j + macroBlockHeight < height && i > 0 && j > 0){
                    int[] diff = new int[]{topLeft[0]-i,topLeft[1]-j};
                    double temp = meanAbsoluteDifference(i,j, diff);
                    if(temp < mad){
                        mad = temp;
                        bestMatchCoord = new int[]{i,j};
                    }
                }
            }
        }
        //System.out.println("current tracking area: ("+topLeft[0]+", "+topLeft[1]+")");
        //System.out.println("current tracking area width: "+macroBlockWidth+", height: "+macroBlockHeight);
        //System.out.println("best match: ("+bestMatchCoord[0]+", "+bestMatchCoord[1]+")");
        if(mad == ERROR_THRESHOLD){
            return null;
        }else{
            TrackingArea match = new TrackingArea();
            match.setTopLeftAndBottomRight(bestMatchCoord, new int[]{bestMatchCoord[0]+macroBlockWidth, bestMatchCoord[1]+macroBlockHeight});
            return match;
        }        
    }
    
    public double meanAbsoluteDifference(int x, int y, int[] diff){
        double sum = 0.0;
        int m = 0;
        int n= 0;
        for(int i = y; i < macroBlockHeight; i++){
            for(int j = x; j < macroBlockWidth; j++){
                //if(j < targetFrame.getWidth() && i < targetFrame.getHeight()){
                     double temp = Math.abs(targetFrame.getRGB(j, i) - referenceFrame.getRGB(j+diff[0], i+diff[1]));
                     sum += temp;
                     m = j;
                     n = i;
                //}               
            }
        }
        m+=1;
        n+=1;
        double mad = (double)(sum/(m*n));
        return mad;
    }
}
